If we want to add localization to a React app, we can use the react-i18next NPM package to do it.
In this article, we’ll look at how to load translations with the withTranslation
higher-order component.
withTranslation
The withTranslation
higher-order component lets us wrap our component to let us gain access to the t
function and i18n
object.
For example, we can write:
import React from "react";
import i18n from "i18next";
import { initReactI18next, withTranslation } from "react-i18next";
const resources = {
en: {
ns1: {
"Welcome to React": "Welcome to React and react-i18next"
}
}
};
i18n.use(initReactI18next).init({
resources,
lng: "en",
keySeparator: false,
interpolation: {
escapeValue: false
}
});
function App({ t }) {
return (
<div className="App">
<p>{t("Welcome to React")}</p>
</div>
);
}
export default withTranslation("ns1")(App);
We called the withTranslation
higher-order component with the namespace to load the ns1
translation namespace.
Also, we can load multiple namespaces with it.
For example, we can write:
import React from "react";
import i18n from "i18next";
import { initReactI18next, withTranslation } from "react-i18next";
const resources = {
en: {
ns1: {
"Welcome to React": "Welcome to React and react-i18next"
},
ns2: {
Hello: "Hello World"
}
}
};
i18n.use(initReactI18next).init({
resources,
lng: "en",
keySeparator: false,
interpolation: {
escapeValue: false
}
});
function App({ t }) {
return (
<div className="App">
<p>{t("Welcome to React")}</p>
<p>{t("ns2:Hello")}</p>
</div>
);
}
export default withTranslation(["ns1", "ns2"])(App);
to load the ns1
and ns2
namespaces.
Any namespace after the first needs the namespace name.
Overriding the i18next Instance
We can override the i18next
instance, by passing an object to the i18n
prop:
import React from "react";
import i18n from "i18next";
import { initReactI18next, withTranslation } from "react-i18next";
const resources = {
en: {
ns1: {
"Welcome to React": "Welcome to React and react-i18next"
},
ns2: {
Hello: "Hello World"
}
}
};
i18n.use(initReactI18next).init({
resources,
lng: "en",
keySeparator: false,
interpolation: {
escapeValue: false
}
});
const MyComponent = ({ t }) => {
return (
<div className="App">
<p>{t("Welcome to React")}</p>
</div>
);
};
const ExtendedComponent = withTranslation("ns1")(MyComponent);
export default function App() {
return (
<div className="App">
<ExtendedComponent i18n={i18n} />;
</div>
);
}
We pass it into the ExtendedComponent
which is created from the withTranslation
component.
Also, we can disable the use of the Suspense
component with the useSuspense
prop.
For example, we can write:
import React from "react";
import i18n from "i18next";
import { initReactI18next, withTranslation } from "react-i18next";
const resources = {
en: {
translation: {
"Welcome to React": "Welcome to React and react-i18next"
}
}
};
i18n.use(initReactI18next).init({
resources,
lng: "en",
keySeparator: false,
interpolation: {
escapeValue: false
}
});
const MyComponent = ({ t, tReady }) => {
return (
<div className="App">
<p>{tReady && t("Welcome to React")}</p>
</div>
);
};
const ExtendedComponent = withTranslation()(MyComponent);
export default function App() {
return (
<div className="App">
<ExtendedComponent useSuspense={false} />
</div>
);
}
If we set useSuspense
to false
, then we have to use the tReady
prop to check if the translation is ready.
Conclusion
The react-i18next NPM package has the withTranslation
higher-order component to provide the required translations functions and objects via the props.